import groovy.sql.Sql
import java.sql.SQLException

def dbUsername = "root"
def dbPassword = "123"
def dbUrl = "jdbc:mysql://localhost:3306/tools"
def dbDriver = "com.mysql.jdbc.Driver"

def sql = Sql.newInstance(dbUrl, dbUsername,
                      dbPassword, dbDriver)

def reservedUrls = ["css", "tablecloth", "secure"]
def validProtocols = ["http://", "https://", "ftp://", "rtsp://"]

if (!request.getAttribute("key").equals("")) {
  shorturl = request.getAttribute("key")
  row = sql.firstRow("select * from urls where shorturl = ?", [shorturl])
  if (row == null) {
    println "Unknown URL requested."
  } else {
    sql.executeUpdate("update urls set ACCESSES = ACCESSES+1, LASTACCESSED = NOW() where shorturl = ?", [shorturl])
    if (row.metarefresh) {
      html.html()
      {
        head()
        {
          title 'Redirecting...'
          meta('http-equiv':'refresh', content:('0;url=' + row.url))
        }
        body()
        {
          h1 'Redirecting...'

          p() {
            span 'Redirecting you to '
            a(href:row.url, row.url)
          }
        }
      }
    } else {
      response.sendRedirect(row.url)
    }
    return
  }
} else {
  html.html()
  {
    head()
    {
      title 'grURLy shortening service'
      print """
      <link rel="stylesheet" href="css/blueprint/screen.css" type="text/css" media="screen, projection">
      <link rel="stylesheet" href="css/blueprint/print.css" type="text/css" media="print">
      <!--[if lt IE 8]><link rel="stylesheet" href="css/blueprint/ie.css" type="text/css" media="screen, projection"><![endif]-->
      <link rel="stylesheet" href="css/blueprint/plugins/fancy-type/screen.css" type="text/css" media="screen, projection" />
      <link href="tablecloth/tablecloth.css" rel="stylesheet" type="text/css" media="screen" />
      <script type="text/javascript" src="tablecloth/tablecloth.js"></script>
      """
    }
    body()
    {
      div(class:'container') {

        h1 'grURLy shortening service'

        def baseUrl = 'http://' + request.getServerName() + ((request.getServerPort() != 80) ? (':' + request.getServerPort()) : '') + '/'
        if (request.getMethod().equalsIgnoreCase("post")) {
          def originalUrl = request.getParameter("originalUrl")
          def validProtocol = false
          validProtocols.each() {
            if (originalUrl.startsWith(it))
              validProtocol = true
          }
          if (!validProtocol)
            originalUrl = 'http://' + originalUrl
          row = sql.firstRow("select * from urls where URL = ?", [originalUrl])

          shortUrl = null
          meta = request.getParameter("meta")!=null?1:null
          fullShortUrl = baseUrl
          if (row == null) {
            insertOk = false
            if (!request.getParameter("shortUrl").equals("")) {
              shortUrl = request.getParameter("shortUrl")
              if (reservedUrls.contains(shortUrl)) {
                span 'Sorry :('
                span 'The short URL you tried to use is not available.'
              } else {
                try {
                  sql.execute("insert into urls (URL, SHORTURL, METAREFRESH) VALUES (?, ?, ?)", [originalUrl, shortUrl, meta])
                  if (sql.updateCount == 1) {
                   insertOk = true
                  }
                } catch (SQLException e) {
                  span 'URL shortening failed! :('
                  br()
                  if (e.getSQLState().startsWith("23")) {
                    p() {
                      strong(baseUrl + shortUrl)
                      span ' is already in use.'
                    }
                  }
                }
              }
            } else {
              row = sql.firstRow("select value from options where `key` = 'next.id'")
              nextid = Integer.parseInt(row.value)

              sql.withTransaction {
                while (!insertOk) {
                  try {
                    shortUrl = Integer.toString(nextid, 36)
                    while (reservedUrls.contains(shortUrl)) {
                      nextid++
                      shortUrl = Integer.toString(nextid, 36)
                    }

                    insertOk = sql.execute("insert into urls (URL, SHORTURL, METAREFRESH) VALUES (?, ?, ?)", [originalUrl, shortUrl, meta])
                    if (sql.updateCount == 1) {
                      insertOk = true
                    }
                    nextid++
                  } catch (SQLException sqle) {
                    if (sqle.getSQLState().startsWith("23")) { // Duplicate key, let's try the next one until we get a free one
                      nextid++
                    } else {
                      throw new Exception(sqle)
                    }
                  } catch (Exception e) {
                    span 'URL shortening failed! :('
                    br()
                    code(e.getMessage())
                  }
                }
                sql.executeUpdate("update options set value = ? where `key` = 'next.id'", [nextid])
              }
            }
            
            if (insertOk) {
                fullShortUrl += shortUrl
                span 'URL shortened!'
                span 'Go to: '
                a(href:fullShortUrl, fullShortUrl)
            }
          } else {
            fullShortUrl += row.shortUrl
            span 'URL is already shortened! :)'
            br()
            span 'Use this one instead: '
            a(href:fullShortUrl, fullShortUrl)
          }

        } else {
          h2 'Shorten URL'          
          form(method : 'POST' , action : '/', name : 'urlshortener')
          {
            label 'Original URL'
            input(type:'text', name:'originalUrl')
            br()
            label 'Short URL (optional): '
            span(baseUrl)
            input(type:'text', name:'shortUrl')
            br()
            input(type:'checkbox', name:'meta')
            label 'Use META-REFRESH type redirect'
            br()
            input(type:'submit', value:'Shorten!')
            br()
            br()
          }

          h2 'Latest 20 short URLs'
          table() {
            tr() {
              th 'URL'
              th 'Created'
              th 'Clicks'
            }
            sql.eachRow("select * from urls order by created desc limit 20") { row ->
              tr() {
                td() {
                  a(href:baseUrl + row.shorturl, row.url)
                }
                td(row.created.format('dd.MM.yyyy HH:mm'))
                td(row.accesses)
              }
            }
          }            
        }
      }
    }
  }
}